home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1992 by Panagiotis Tsirigotis
- * All rights reserved. The file named COPYRIGHT specifies the terms
- * and conditions for redistribution.
- */
-
- static char RCSid[] = "$Id: special.c,v 5.2 1992/11/10 08:18:25 panos Exp $" ;
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <syslog.h>
- #include <signal.h>
-
- #include "misc.h"
-
- #include "options.h"
-
- #include "attr.h"
- #include "conf.h"
- #include "server.h"
- #include "state.h"
- #include "config.h"
- #include "builtin.h"
- #include "connection.h"
-
- void msg() ;
- void out_of_memory() ;
-
- extern struct name_value socket_types[] ;
-
- #define LOG_SERVICE_NAME "logging"
- #define SHUTDOWN_SERVICE_NAME "shutdown"
-
- void stream_logging() ;
- void stream_shutdown() ;
- void intercept() ;
-
- static struct builtin_service special_services[] =
- {
- { LOG_SERVICE_NAME, SOCK_STREAM, stream_logging, FORK },
- { SHUTDOWN_SERVICE_NAME, SOCK_STREAM, stream_shutdown, FORK },
- { INTERCEPT_SERVICE_NAME, SOCK_STREAM, intercept, FORK },
- { INTERCEPT_SERVICE_NAME, SOCK_DGRAM, intercept, FORK },
- { NULL }
- } ;
-
-
-
- /*
- * Add the special services to the service table
- */
- void include_special_services()
- {
- int instances ;
- struct service *setup_special_service() ;
-
- instances = logprocs_option ? logprocs_option_arg : DEFAULT_LOGPROCS ;
- LOG_SERVICE( ps ) = setup_special_service(
- LOG_SERVICE_NAME, SOCK_STREAM, instances ) ;
-
- instances = shutdownprocs_option ? shutdownprocs_option_arg
- : DEFAULT_SHUTDOWNPROCS ;
- SHUTDOWN_SERVICE( ps ) = setup_special_service(
- SHUTDOWN_SERVICE_NAME, SOCK_STREAM, instances ) ;
- }
-
-
- struct builtin_service *find_special_builtin( service_name, type )
- char *service_name ;
- int type ;
- {
- register struct builtin_service *bsp ;
- struct name_value *nvp ;
- char *func = "find_special_builtin" ;
-
- if ( bsp = builtin_lookup( special_services, service_name, type ) )
- return( bsp ) ;
-
- nvp = nv_find_name( socket_types, type ) ;
- if ( nvp == NULL )
- {
- msg( LOG_ERR, func, "unknown socket type: %d", type ) ;
- return( NULL ) ;
- }
-
- msg( LOG_ERR, func,
- "special service %s,%s not supported", service_name, nvp->name ) ;
- return( NULL ) ;
- }
-
-
- PRIVATE status_e special_service_handler( sp, cp )
- struct service *sp ;
- connection_s *cp ;
- {
- if ( svc_access_control( sp, cp ) == FAILED ||
- server_run( sp, cp ) == FAILED )
- {
- if ( sp == SHUTDOWN_SERVICE( ps ) )
- conn_shutdown( cp ) ;
- return( FAILED ) ;
- }
- return( OK ) ;
- }
-
-
- PRIVATE struct service *setup_special_service( name, socket_type, instances )
- char *name ;
- int socket_type ;
- int instances ;
- {
- struct builtin_service *bsp ;
- struct service *sp ;
- struct service_config sconf ;
- status_e make_conf() ;
- void special_postmortem() ;
-
- bsp = find_special_builtin( name, socket_type ) ;
- if ( bsp == NULL )
- return( NULL ) ;
-
- if ( make_conf( &sconf, name, instances ) == FAILED )
- return( NULL ) ;
-
- sp = svc_new( &sconf ) ;
- if ( sp == NULL )
- {
- sconf_free( &sconf ) ;
- return( NULL ) ;
- }
-
- sp->state = SVC_ACTIVE ;
- sp->builtin = bsp ;
- SDATA( sp )->postmortem = special_postmortem ;
- SDATA( sp )->handler = special_service_handler ;
- SDATA( sp )->log_handle = ps.rws.program_log ;
- SVC_HOLD( sp ) ;
- return( sp ) ;
- }
-
-
- PRIVATE status_e make_conf( scp, name, instances )
- register struct service_config *scp ;
- char *name ;
- int instances ;
- {
- char *func = "make_conf" ;
-
- CLEAR( *scp ) ;
-
- M_SET( scp->type, ST_INTERNAL ) ;
- M_SET( scp->type, ST_SPECIAL ) ;
- SPECIFY( scp, A_TYPE ) ;
-
- M_SET( scp->flags, SF_NORETRY ) ;
- SPECIFY( scp, A_FLAGS ) ;
-
- scp->instances = instances ;
- SPECIFY( scp, A_INSTANCES ) ;
-
- scp->name = make_string( 1, name ) ;
- if ( scp->name == NULL )
- {
- out_of_memory( func ) ;
- return( FAILED ) ;
- }
-
- scp->id = make_string( 1, scp->name ) ;
- if ( scp->id == NULL )
- {
- free( scp->name ) ;
- out_of_memory( func ) ;
- return( FAILED ) ;
- }
- SPECIFY( scp, A_ID ) ;
-
- scp->wait = NO ;
- SPECIFY( scp, A_WAIT ) ;
-
- return( OK ) ;
- }
-
-
-
- PRIVATE void stream_logging( serp )
- struct server *serp ;
- {
- void log_remote_user() ;
-
- #ifdef DEBUG_LOGGING
- if ( debug.on )
- {
- msg( LOG_DEBUG, "stream_logging", "%d is sleeping", getpid() ) ;
- sleep( 10 ) ;
- }
- #endif
-
- log_remote_user( serp ) ;
- }
-
-
-
- PRIVATE void stream_shutdown( serp )
- struct server *serp ;
- {
- struct service *sp = SERVER_CONNECTION( serp )->sp ;
- char *str = NULL ;
- void logprint() ;
- char *func = "stream_shutdown" ;
-
- if ( debug.on )
- msg( LOG_DEBUG, func, "shutdown for service %s, (fd=%d)",
- CONF( sp )->id, SERVER_FD( serp ) ) ;
-
- #ifdef DEBUG_SHUTDOWN
- /*
- * The reason for the sleep is that single stepping through this
- * code is impossible (at least on the Sun IPC I am using).
- */
- if ( debug.on )
- {
- msg( LOG_DEBUG, func, "%d is sleeping", getpid() ) ;
- sleep( 10 ) ;
- }
- #endif
-
- /*
- * Everything must happen within 10 seconds.
- * Since there is no alarm handler the process will be terminated if the
- * timer runs out.
- */
- if ( ! debug.on )
- {
- (void) alarm( 10 ) ;
- (void) signal( SIGALRM, SIG_DFL ) ;
- }
-
- (*SDATA( sp )->shutdown)( SERVER_FD( serp ), &str ) ;
-
- (void) alarm( 0 ) ;
-
- if ( str != NULL )
- logprint( sp, "DATA", "%s", str ) ;
- }
-
-
- PRIVATE void special_postmortem( serp )
- struct server *serp ;
- {
- connection_s *cp = SERVER_CONNECTION( serp ) ;
-
- if ( conn_start_alternative( cp ) == FAILED )
- {
- xlog_control(
- SDATA( SERVER_SERVICE( serp ) )->log_handle, XLOG_SIZECHECK ) ;
- conn_free( cp ) ;
- }
- }
-
-